TalendでtJavaを使用してJavaでマスキング処理。
はじめに
Talendには様々なコンポーネントが用意されていますが、細かいところはコードを書いて対応したいという事があります。その時には「tJava」を使用すれば解決します。 TalendはEclipseを元に開発されている様なので、プログラミング画面はまんまEclipseです。
環境
Mac OSX 10.10.5 Yosemite Talend Open Studio for Data Integration 5.6.2 JDK 1.7.0_79
プログラムの目的
TSVファイルの項目別の対応でマスキングし、新規TSVファイルを出力する。
TSV
id name post address tel 12345678901 madonna louise ciccone 010-1101 神奈川県横浜市XX区YY町111 045-011-0011 23456789012 prince rogers nelson 011-0010 埼玉県三郷市YY町010 070-1100-1100 34567890123 michael joseph jackson 110-1001 千葉県船橋市YY町101 090-1001-0110 45678901234 中田 ヤステル 222-2222 東京都中野区XX222 080-2222-2222 56789012345 小室 哲夫 333-3333 東京都府中市YY町333 080-3333-3333
左から、登録番号、登録者名、郵便番号、住所、電話番号。
Talend:コンポーネント配置
Talend:コンポーネント設定
tFileInputDelimited
TSVを読み込むコンポーネント。
基本設定
ファイル名/ストリーム: 読み込むファイルパス 行区切り記号: 改行コード フィールド区切り記号: 今回はTSVなので「\t」 ヘッダー: TSVのヘッダーは不要なので「1」 スキーマの編集: 押下してTSVとレイアウトを合わせたものを作成。「➕」でカラム追加できます。
Advanced setting
エンコード: 任意の文字コード(今回はUTF-8)
tJava
Javaコードを書いてメソッドを定義できます。 使用するメソッドは下のの様に書いておきます。コード内容は後述。
tMap
tMapアイコンをダブルクリックするか、「コンポーネント」>「基本設定」>「マップエディタ」を押下してウィンドウを開き、下の画像の様に設定します。 カラム名をドラッグして真ん中のウィンドウ(「Var」と表示されている箇所)に持っていくとtMapに登録されます。 項目「式」にtJavaで設定したメソッドを記述できます。 設定したら、「tFileOutputDelimited」の対応するカラム名にドラッグして接続して完成。 最初はカラム名が表示されていないと思うので、先に「tFileOutputDelimited」で「カラム名の同期」を実行しておくと楽です。
各カラムのtMapの設定は下記の様にします。
SampleClass.maskingId(row2.id) SampleClass.toHeadUpper(SampleClass.maskingName(row2.name)) SampleClass.maskingPostal(row2.postal) SampleClass.maskingAddress(row2.address) SampleClass.maskingNumber(row2.tel)
tFileOutputDelimited
TSVを出力します。
基本設定
ファイル名: TSVファイルの出力先パス 行区切り記号: 改行コード フィールド区切り記号: TSVなので「\t」 ヘッダーを含むにチェックを入れれば、Talendで設定したカラム名がヘッダーになります。
Advanced settings
ここはお好みで。
tJavaでコード作成
準備
1、画面左のリポリジトリの「コード」を右クリックして「フォルダを作成」。 2、作成したフォルダを右クリックして「コードを作成」。 3、Eclipseライクなプログラミング画面が表示されます。
必要なメソッド
今回はカラムごとにマスキング方法が違うので、下記を用意します。
カラム名 | 対応するメソッド | 内容 |
---|---|---|
id | maskingId | 登録ID。3〜7桁目を「*」に置換。 |
name | maskingName | 登録者名。最初と最後の文字を「*」に置換。 |
name | toHeadUpper | 登録者名の頭文字が半角英字の場合に頭文字を大文字にする。 |
postal | maskingPostal | 郵便番号。「-」を削除し、下4桁を「*」に置換。 |
address | maskingAddress | 住所。2〜4、6〜8、10〜14文字目を「*」に置換。 |
tel | maskingNumber | 電話番号。「-」以外を全て「*」に置換。 |
マスキング処理のコード作成
package routines; public class SampleClass { /** * {talendTypes} String * {Category} User Defined * 3〜7文字を「*」にする。 * @return */ public static String maskingId(String input) { StringBuilder sb = new StringBuilder(); if (input != null) { // 引数の文字列を分割 for (int i = 0; i < input.length(); i++) { // 分割した文字の3〜7文字目()を「*」に置換。 if (i>=2 && i<=6) { sb.append("*"); } // それ以外はそのまま。 else { sb.append(input.substring(i, i+1)); } } return sb.toString(); } return input; } /** * {talendTypes} String * {Category} User Defined * 引数の文字列の最初と最後を「*」に置換する。 * @param input * @return */ public static String maskingName(String input) { // 前後の空白を削除 input = input.trim(); // 名前の文字数を取得 int count = input.length(); // 引数の文字数で分岐 if (count > 1) { // 準備 String asterisk = "*"; String output = ""; StringBuilder sb = new StringBuilder(); for (int i = 0; i < count; i++) { // 最初と最後は「*」 if (i==0 || i==count-1) { sb.append(asterisk); } else { sb.append((input.substring(i, i+1))); } } output = sb.toString(); return output; } else if (count == 1) { // 1文字なので「*」を返す。 return "*"; } else { // 0文字なので入力された引数をそのまま返す。 return input; } } /** * {talendTypes} String * {Category} User Defined * 引数の文字列をfirst,middle,lastに分け、それぞれの頭文字を大文字にする。 * @param input * @return */ public static String toHeadUpper(String input) { // 準備 StringBuilder sb = new StringBuilder(); String output = ""; // 1.文字列を空白で分割 String[] strSplit = input.split(" "); int splitLength = strSplit.length; // 2.分割した要素分(苗字と名前など)、頭文字を大文字にする for (int j = 0; j < splitLength; j++) { sb.setLength(0); // ループ毎に初期化 // 3.頭文字を抽出 String top = strSplit[j].substring(0,1); // 4.頭文字が正規表現で先頭が[a-z]の場合 // 正規化の準備(英字小文字の場合は頭文字を大文字にする) Pattern p = Pattern.compile("^[a-z]"); // 文字列の先頭が[a-z] if (p.matcher(top).find()) { // 4-1.文字目以降の文字列を取得 String end = strSplit[j].substring(1, strSplit[j].length()); // 4-2.先頭を大文字に置換 sb.append(top.toUpperCase()); sb.append(end); } else { // 4.先頭が英字小文字でない場合はそのままSBに結合 sb.append(strSplit[j]); } // 5.名前同士の間に半角空白入れる(最後じゃない場合) if (j != splitLength-1) { sb.append(" "); } output += sb.toString(); } // 最初と最後を「*」に置き換えた文字列を返す。 return output; } /** * {talendTypes} String * {Category} User Defined * "-"を削除。郵便番号で使用。 * @return */ public static String maskingPostal(String input) { // 「-」を削除して、右から4桁を「*」に置換 return input.substring(0, 3) + "****"; } /** * {talendTypes} String * {Category} User Defined * 住所の2〜4、6〜8、10〜14文字目を*に置換する。 * @return */ public static String maskingAddress(String input) { if (input != null) { StringBuilder sb = new StringBuilder(); // 引数の文字列を分割 for (int i = 0; i < input.length(); i++) { // 分割した文字の2〜4、6〜8、10〜14文字目を「*」に置換。 if ((i>=1 && i<=3) || (i>=5 && i<=9) || (i>=11 && i<=15)) { sb.append("*"); } // それ以外はそのまま。 else { sb.append(input.substring(i, i+1)); } } // 文字列を返す。 return sb.toString(); } return input; } /** * {talendTypes} String * {Category} User Defined * 電話番号が"-"以外を「*」に変換して返す。 * @param number 電話番号。 * @return String */ public static String maskingNumber(String number) { char[] c = number.toCharArray(); StringBuilder sb = new StringBuilder(); /* * Stringをchar配列に分割し、一文字ずつ条件に当てはめて行く。 * '-'ではなく、15文字より手前なら、「*」をStringに入れる。 * それ以外は、charをそのままStringに入れる。 */ for (int i = 0; i < c.length; i++) { if (c[i]!='-') { sb.append("*"); } else { sb.append(Character.toString(c[i])); } } // 文字列を返す return sb.toString(); } }
注意点:メソッドは「public static」とします。「private」にするとtMapで利用できなかったと思います。
また、メソッドのドキュメンテーションコメントに下記を書いておくとtMapの式ビルダのカテゴリ「ユーザー定義」に表示されます。
/** * {talendTypes} String * {Category} User Defined */
実行結果
id name postal address tel 12*****8901 *adonna Louise Ciccon* 010**** 神***横*****Y***** ***-***-**** 23*****9012 *rince Rogers Nelso* 011**** 埼***郷*****1* ***-****-**** 34*****0123 *ichael Joseph Jackso* 110**** 千***橋*****0* ***-****-**** 45*****1234 *田 ヤステ* 222**** 東***野*****2 ***-****-**** 56*****2345 *室 哲* 333**** 東***中*****3* ***-****-****
さいごに
今回は文字をマスキングする方法を書きましたが、カラム自体を隠してしまう方法もあります。